package com.ozo.boot.auth.token;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.ozo.boot.auth.constant.RedisKeyConstant;
import com.ozo.boot.auth.exception.AuthExceptionEnum;
import com.ozo.boot.auth.log.LoginLogEvent;
import com.ozo.boot.auth.log.LoginLogUtil;
import com.ozo.boot.auth.pojo.dto.LoginDTO;
import com.ozo.boot.common.base.constant.StatusEnum;
import com.ozo.boot.common.base.model.LoginUser;
import com.ozo.boot.common.base.model.ResultVO;
import com.ozo.boot.common.core.exception.ServiceException;
import com.ozo.boot.manage.pojo.vo.SysUserInfoVO;
import com.ozo.boot.manage.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

/**
 * <p>
 * 账号密码登录
 * </p>
 *
 * @author qiangesoft
 * @since 2024-07-11
 */
@RequiredArgsConstructor
@Component("PASSWORD")
public class PasswordTokenGranter extends AbstractTokenGranter {

    private final ISysUserService sysUserService;

    private final RedisTemplate<String, String> redisTemplate;

    @Override
    public LoginUser login(LoginDTO loginDTO) {
        // 验证码校验
        String username = loginDTO.getUsername();
        String password = loginDTO.getPassword();
        String captcha = loginDTO.getCaptcha();
        String captchaUUID = loginDTO.getCaptchaUUID();
        String captchaText = redisTemplate.opsForValue().get(RedisKeyConstant.CAPTCHA + captchaUUID);
        if (captchaText != null) {
            redisTemplate.delete(RedisKeyConstant.CAPTCHA + captchaUUID);
        }
        if (!captcha.equals(captchaText)) {
            SpringUtil.publishEvent(new LoginLogEvent(LoginLogUtil.fail(username, JSONUtil.toJsonStr(ResultVO.fail(AuthExceptionEnum.CAPTCHA_ERROR)))));
            throw new ServiceException(AuthExceptionEnum.CAPTCHA_ERROR);
        }

        SysUserInfoVO sysUserVO = sysUserService.getByUsername(username);
        if (sysUserVO == null) {
            SpringUtil.publishEvent(new LoginLogEvent(LoginLogUtil.fail(username, JSONUtil.toJsonStr(ResultVO.fail(AuthExceptionEnum.USERNAME_OR_PASSWORD_ERROR)))));
            throw new ServiceException(AuthExceptionEnum.USERNAME_OR_PASSWORD_ERROR);
        }
        if (StatusEnum.DISABLE.getCode().equals(sysUserVO.getStatus())) {
            SpringUtil.publishEvent(new LoginLogEvent(LoginLogUtil.fail(username, JSONUtil.toJsonStr(ResultVO.fail(AuthExceptionEnum.ACCOUNT_DISABLED)))));
            throw new ServiceException(AuthExceptionEnum.ACCOUNT_DISABLED);
        }
        boolean matches = SecureUtil.md5(password).equals(sysUserVO.getPassword());
        if (!matches) {
            SpringUtil.publishEvent(new LoginLogEvent(LoginLogUtil.fail(username, JSONUtil.toJsonStr(ResultVO.fail(AuthExceptionEnum.USERNAME_OR_PASSWORD_ERROR)))));
            throw new ServiceException(AuthExceptionEnum.USERNAME_OR_PASSWORD_ERROR);
        }

        return this.doLogin(sysUserVO, loginDTO.getRememberMe());
    }

}
